package org.fatewa.engine.advice.protocol;

import core.MultipartData;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.http.HttpStatus;

/**
 * 返回的协议内容
 * 在 spring-cli 1.x 中我们使用 ProtocolResponse 的 toData 函数进行数据的转换
 * 导致在实际的使用中，几乎很难看到 ProtocolResponse 被使用
 * 综合考虑后本次实现直接继承 MultipartData
 * 因此该类也获得了灵活的数据转换能力，同时将 code、msg 作为固定字段确保一定的静态类型限制
 * 同时也会提供灵活的策略机制激励用户按需实现自己的返回策略
 *
 * @author 4everlynn
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class RayquazaResponse extends MultipartData {

    public static final String KEY_CODE = "code";
    public static final String KEY_MSG = "message";

    public static final String KEY_DATA = "data";
    public static final String KEY_LINKS = "links";
    public static final String KEY_ERRORS = "errors";

    public static final String MSG_SUCCESS = "success";

    /**
     * 完整的构造器，可以指定数据、http 状态码与消息
     *
     * @param data 数据
     * @param code 状态码
     * @param msg  消息
     * @param <T>  数据类型
     */
    public <T> RayquazaResponse(T data, Integer code, String msg) {
        this.code(code);
        this.msg(msg);
        this.data(data);
    }


    /**
     * 使用一个参数构造器时，默认为数据 + 成功响应
     *
     * @param data 数据
     * @param <T>  数据类型
     */
    public <T> RayquazaResponse(T data) {
        this(data, HttpStatus.OK.value(), MSG_SUCCESS);
    }

    /**
     * 使用无参数构造器时，默认为成功响应
     */
    public RayquazaResponse() {
        this(null, HttpStatus.OK.value(), MSG_SUCCESS);
    }


    public Integer code() {
        return this.getIntegerPart(KEY_CODE);
    }

    public <T> RayquazaResponse data(T data) {
        this.include(KEY_DATA, data);
        return this;
    }


    public String msg() {
        return this.getStringPart(KEY_MSG);
    }

    public String links() {
        return this.getStringPart(KEY_LINKS);
    }

    public RayquazaResponse links(HttpStatus status) {
        this.include(KEY_CODE, status.value());
        return this;
    }

    public RayquazaResponse errors(Exception exception) {
        this.include(KEY_ERRORS, exception);
        return this;
    }

    public Exception errors() {
        return getPart(KEY_ERRORS, Exception.class);
    }

    public RayquazaResponse code(int code) {
        this.include(KEY_CODE, code);
        return this;
    }

    public RayquazaResponse code(HttpStatus status) {
        this.include(KEY_CODE, status.value());
        return this;
    }

    public RayquazaResponse msg(String msg) {
        this.include(KEY_MSG, msg);
        return this;
    }

}
